package org.sunspotworld;



/*
 * StartApplication.java
 *
 * Created on Jul 29, 2009 9:25:31 AM;
 */

import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.peripheral.radio.RadioFactory;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.peripheral.radio.RadioPolicyManager;
import com.sun.spot.sensorboard.peripheral.LEDColor;
import com.sun.spot.util.*;

import java.io.*;
import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 *A Robot Lazor Game
 *
 * @author Tomas Henriquez, Sabin Larrañaga
 *
 */
public class StartApplication extends MIDlet {
    public static final int CONNECT_PORT = 23;
    public static final int RUN_PORT = 20;

    public static final byte ROBOT_SIGNATURE = 4;
    public static final byte LAZER_SIGNATURE = 32;
    public static final byte CONTROL_SIGNATURE = 17;

    private static final short PID = 4;
    private static final int CHANNEL = 23;

    private static ITriColorLED[] leds = EDemoBoard.getInstance().getLEDs();
    private Radiogram rrg;

    private String controlAddr = null;
    private RadiogramConnection conn = null;

    private static boolean flag = false;

    private Thread lazerThread = new Thread() {
        public void run() {
            lazorKill();
        }
    };

    private void connect() {
        try {
            conn = (RadiogramConnection) Connector.open("radiogram://:"+CONNECT_PORT);
            rrg = (Radiogram)conn.newDatagram(conn.getMaximumLength());
            Radiogram xrg = (Radiogram)conn.newDatagram(conn.getMaximumLength());
            xrg.reset();
            xrg.writeByte(LAZER_SIGNATURE);
            conn.receive(rrg);
            if (rrg.readByte() != CONTROL_SIGNATURE) {
                return;
            }
            xrg.setAddress(rrg);
            conn.send(xrg);
            controlAddr = rrg.getAddress();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        if (conn != null) {
            try {
                conn.close();
                conn = null;
                rrg = null;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private void blinkConnected() {
        for (int i=0; i<3; i++) {
            for (int j=0; j<leds.length; j++) {
                leds[j].setColor(LEDColor.GREEN);
                leds[j].setOn();
            }
            Utils.sleep(500);
            for (int j=0; j<leds.length; j++) {
                leds[j].setOff();
            }
            Utils.sleep(500);
        }
    }

    protected void startApp() throws MIDletStateChangeException {
        new BootloaderListener().start();   // monitor the USB (if connected) and recognize commands from host

        RadioPolicyManager rpm = (RadioPolicyManager) RadioFactory.getRadioPolicyManager();

        //Here we set the Pan and Channel numbers
        rpm.setPanId(PID);
        rpm.setChannelNumber(CHANNEL);

        leds[0].setColor(LEDColor.RED);
        leds[0].setOn();
        
        while (controlAddr == null) {
            connect();
        }
        blinkConnected();
        //We start a server so he can lisen to every radiogram that the Wii Remote Control may send
        try {

            conn = (RadiogramConnection) Connector.open("radiogram://"+controlAddr+":"+RUN_PORT);

            rrg = (Radiogram) conn.newDatagram(conn.getMaximumLength());
            double value = 0; //we inistialize the value
            while (true) {
                rrg.reset();
                conn.receive(rrg);

                value = rrg.readInt(); //here we read the value frmo the Wii Remote Control, it should be always 1, but just to make sure we validate it

                if (value == 1) {
                    new Thread(lazerThread).start();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if(conn != null){
                    conn.close();
                    conn = null;
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    // cause the MIDlet to exit
    }

    /**
     *
     *
     *@Return
     *
     *  We launch the laser to mutilate the other robot we our lazor pain slasher for 2 seconds.
     */
    private static void lazorKill() {
        synchronized (leds) {
            if (flag) {
                return;
            }
            flag = true;
        }
        for (int i = 0; i < leds.length; i++) {
            leds[i].setRGB(255, 255, 255);
            leds[i].setOn();
        }

        Utils.sleep(2000);

        for (int i = 0; i < leds.length; i++) {
            leds[i].setOff();
        }

        charging();
        flag = false;
    }


    private static void ledsOn(LEDColor color,int length){
         for (int i = 0; i < length; i++) {
            leds[i].setColor(color);
            leds[i].setOn();
        }
    }

    private static void ledsOff(){
        for (int i = 0; i < leds.length; i++) {
            leds[i].setOff();
        }
    }
    /**
      *  We light on yellow lights 1 every 0.5 seconds and in the last one they all become green for 1 second.
      */
    private static void charging() {

        for (int i = 0; i < 7; i++) {
            leds[i].setRGB(30, 30, 0);
            leds[i].setOn();
            Utils.sleep(500);
        }

        ledsOff();

        ledsOn(new LEDColor(0,30,0) ,8);
/*
        for (int i = 0; i < 8; i++) {
            leds[i].setRGB(0, 30, 0);
            leds[i].setOn();
        }
*/
        Utils.sleep(1000);
        ledsOff();
    }

    protected void pauseApp() {
        // This is not currently called by the Squawk VM
    }

    /**
     * Called if the MIDlet is terminated by the system.
     * I.e. if startApp throws any exception other than MIDletStateChangeException,
     * if the isolate running the MIDlet is killed with Isolate.exit(), or
     * if VM.stopVM() is called.
     *
     * It is not called if MIDlet.notifyDestroyed() was called.
     *
     * @param unconditional If true when this method is called, the MIDlet must
     *    cleanup and release all resources. If false the MIDlet may throw
     *    MIDletStateChangeException  to indicate it does not want to be destroyed
     *    at this time.
     */
    protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
        ledsOff();
    }
}
